package nba2kmodtool.filedesc;

import java.io.File;
import java.io.FileReader;
import java.io.IOException;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Iterator;
import java.util.List;
import java.util.Scanner;

import nba2kmodtool.filedesc.util3d.DX3Dmath;
import nba2kmodtool.util.ByteFileReader;

class N2kObjFileModelImporter {
	private static final boolean IS_DEBUG = BaseIffFile.IS_DEBUG;

	protected BaseIffFile iff;
	protected File file;

	protected N2kObjFileModelImporter(BaseIffFile iff) {
		this.iff = iff;
		this.file = iff.file;
	}

	void importModelFromOBJFile(File modelfile, N2kPackageFile pagFile) throws IOException {
		ByteFileReader out = new ByteFileReader(file, "rw");
		Scanner in = new Scanner(new FileReader(modelfile));
		List<Float> verts = new ArrayList();
		List<Float> uvs = new ArrayList();
		int partIndex = 0;
		int childIndex = 0;
		while (in.hasNextLine()) {
			String tempStr = in.nextLine();
			//part start line
			if (tempStr.equals("g default")) {
				verts.clear();
				uvs.clear();
				continue;
			}
			//part name line(import vertex data at this mark)
			if (!tempStr.equals("g default") && tempStr.indexOf("g ") == 0) {
				int index = tempStr.indexOf('m');
				String[] strs = tempStr.substring(index + 1).replaceAll("[^\\d_]", "").split("_");
				if (IS_DEBUG) {
					System.out.println("partname: " + Arrays.toString(strs) + ", " + tempStr.substring(index + 1));
				}
				partIndex = Integer.parseInt(strs[0]);
				childIndex = Integer.parseInt(strs[1]);
				if (IS_DEBUG) {
					System.out.println("part: " + partIndex + ", " + childIndex);
				}
				N2k3DModelPart model = pagFile.models[partIndex];
				N2k3DChildModelPart child = model.childParts[childIndex];
				if ((verts.size() / 3) != child.vertNum) {
					throw new IOException(String.format("Model Part is Not Matching\nResource: %d-%d %d\nImport: %d",
							partIndex, childIndex, child.vertNum, verts.size()));
				}
				importChildModelFromList(child, out, verts, uvs, model);
				continue;
			}
			//vertex position line
			if (tempStr.indexOf("v ") == 0) {
				String[] vstrs = tempStr.substring(2).split(" ");
				verts.add(Float.parseFloat(vstrs[0]));
				verts.add(Float.parseFloat(vstrs[1]));
				verts.add(Float.parseFloat(vstrs[2]));
				continue;
			}
			//uv position line
			if (tempStr.indexOf("vt ") == 0) {
				String[] uvstrs = tempStr.substring(3).split(" ");
				uvs.add(Float.parseFloat(uvstrs[0]));
				uvs.add(Float.parseFloat(uvstrs[1]));
				continue;
			} else {
			}
		}
		in.close();
		out.close();
	}

	private void importChildModelFromList(N2k3DChildModelPart child, ByteFileReader out, List<Float> verts,
			List<Float> uvs, N2k3DModelPart model) throws IOException {
		int childVertStart = child.vertStart;
		int perVertexSize = model.perVertexSize;
		int perUVNSize = model.perUVNSize;
		int vertexNum = child.vertNum;
		//import vertex position data buffer
		out.seek(model.vertexDataStart + childVertStart * perVertexSize);
		Iterator<Float> vtit = verts.iterator();
		Iterator<Float> uvit = uvs.iterator();
		//model type1
		if (model.dataChunkCount == 1) {
			for (int i = 0; i < vertexNum; i++) {
				out.writeFloatBigEndin(vtit.next().floatValue());
				out.writeFloatBigEndin(vtit.next().floatValue());
				out.writeFloatBigEndin(vtit.next().floatValue());
				if (!model.isUVvalid) {
					out.skipBytes(perVertexSize - 12);
					continue;
				}
				if ((perVertexSize - 12) == 0x28) {
					out.skipBytes(0x18);
					float tu = uvit.next().floatValue();
					float tv = 1.0F - uvit.next().floatValue();
					short[] uv = DX3Dmath.D3DXFloat32To16Array(new float[] { tu, tv });
					out.writeShortBigEndin(uv[0]);
					out.writeShortBigEndin(uv[1]);
					out.skipBytes(0x0C);
					continue;
				} else if ((perVertexSize - 12) == 0x24) {
					out.skipBytes(0x18);
					float tu = uvit.next().floatValue();
					float tv = 1.0F - uvit.next().floatValue();
					short u = (short) (tu * 32767.0F);
					short v = (short) (tv * 32767.0F);
					out.writeShortBigEndin(u);
					out.writeShortBigEndin(v);
					out.skipBytes(0x08);
					continue;
				} else {
					out.skipBytes(perVertexSize - 12);
				}
			}
		}
		//model type2
		else {
			//import vertex position datas
			if (perVertexSize < 12) {
				for (int i = 0; i < vertexNum; i++) {
					float mod = 467.67F;
					float tx = vtit.next().floatValue();
					float ty = vtit.next().floatValue();
					float tz = vtit.next().floatValue();
					short x = (short) (tx * mod);
					short y = (short) (ty * mod);
					short z = (short) (tz * mod);
					out.writeShortBigEndin(x);
					out.writeShortBigEndin(y);
					out.writeShortBigEndin(z);
					out.skipBytes(0x02);
				}
			} else {
				for (int i = 0; i < vertexNum; i++) {
					out.writeFloatBigEndin(vtit.next().floatValue());
					out.writeFloatBigEndin(vtit.next().floatValue());
					out.writeFloatBigEndin(vtit.next().floatValue());
					out.skipBytes(perVertexSize - 12);
				}
			}
			if (!model.isUVvalid) {
				return;
			}
			//import uvn position datas
			out.seek(model.uvnDataStart + perUVNSize * childVertStart);
			if (perUVNSize == 0x28) {
				for (int i = 0; i < vertexNum; i++) {
					out.skipBytes(0x18);
					out.writeFloatBigEndin(uvit.next());
					out.writeFloatBigEndin(1.0F - uvit.next());
					out.skipBytes(0x08);
				}
			} else if (perUVNSize == 0x24) {
				for (int i = 0; i < vertexNum; i++) {
					float mod = 32767F;
					out.skipBytes(0x18);
					float tu = uvit.next();
					float tv = 1.0F - uvit.next();
					short u = (short) (tu * mod);
					short v = (short) (tv * mod);
					out.writeShortBigEndin(u);
					out.writeShortBigEndin(v);
					out.skipBytes(0x08);
				}
			} else if (perUVNSize == 0x18 || perUVNSize == 0x04) {
				for (int i = 0; i < vertexNum; i++) {
					float mod = 32767F;
					float tu = uvit.next();
					float tv = 1.0F - uvit.next();
					short u = (short) (tu * mod);
					short v = (short) (tv * mod);
					out.writeShortBigEndin(u);
					out.writeShortBigEndin(v);
					out.skipBytes((perUVNSize - 0x04));
				}
			} else {
				throw new IOException("UnSupport Nba2K 3D Model Type");
			}
		}
	}
}
